package com.bestcem.xm.survey.service.reportHandler.type;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.survey.service.reportHandler.BaseReportHandler;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.bestcem.xm.survey.util.SurveyConstant.SCORE_RULE_ALL_RIGHT;

@Component
public class MatrixMultipleScoreHandler implements BaseReportHandler {

    @Override
    public Double getMaxScore(JSONObject question, JSONArray scoreRule) {
        if (question == null || question.getJSONArray("items") == null) {
            return 0d;
        }
        JSONArray items = Optional.ofNullable(question.getJSONArray("items")).orElse(new JSONArray());
        JSONArray rowItems = Optional.ofNullable(question.getJSONArray("rows_items")).orElse(new JSONArray());
        JSONObject scoreGidDict = getMatrixScoreGidDict(scoreRule);

        double maxScore = 0d;

        for (int i = 0; i < rowItems.size(); i++) {
            JSONObject rows = rowItems.getJSONObject(i);
            double tmpScore = 0.0;
            List<Double> gte0Score = new ArrayList<>();
            List<Double> lt0Score = new ArrayList<>();

            for (int j = 0; j < items.size(); j++) {
                JSONObject item = items.getJSONObject(j);
                Double score = Optional.ofNullable(scoreGidDict.getDouble(rows.getString("gid") + "_" + item.getString("gid"))).orElse(0d);
                if (score >= 0) {
                    gte0Score.add(score);
                } else {
                    lt0Score.add(score);
                }
            }
            if (CollectionUtils.isNotEmpty(gte0Score)) {
                tmpScore = gte0Score.stream()
                    .mapToDouble(Double::doubleValue)
                    .sum();
            } else if (CollectionUtils.isNotEmpty(lt0Score)) {
                tmpScore = Collections.max(lt0Score);
            }
            maxScore += tmpScore;
        }
        return convertFloat(maxScore);
    }

    @Override
    public Double getScore(JSONObject question, Object answers, JSONArray scoreRule, JSONObject scoreConfig) {
        double score = 0.0;
        JSONObject scoreGidDict = getMatrixScoreGidDict(scoreRule);
        Integer scoreConf = scoreConfig.getInteger(question.getString("gid"));
        JSONObject answersJs = (JSONObject)answers;
        if (answersJs == null || answersJs.isEmpty()) {
            return convertFloat(score);
        }
        List<String> keys = new ArrayList<>(answersJs.keySet());
        for (int i = 0; i < keys.size(); i++) {
            String row = keys.get(i);
            JSONArray item = answersJs.getJSONArray(row);
            List<String> scoreKeys = new ArrayList<>(scoreGidDict.keySet());
            JSONObject scoreGidDic = new JSONObject();
            for (int j = 0; j < scoreKeys.size(); j++) {
                String key = scoreKeys.get(j);
                if (key.startsWith(row)) {
                    scoreGidDic.put(key, scoreGidDict.getDouble(key));
                }
            }
            if (!SCORE_RULE_ALL_RIGHT.equals(scoreConf) || !checkAnswerAllRight(row, scoreGidDic, item)) {
                if (item != null && !item.isEmpty()) {
                    for (int j = 0; j < item.size(); j++) {
                        JSONArray ans = item.getJSONArray(j);
                        score += Optional.ofNullable(scoreGidDict.getDouble(row + "_" + ans.getString(0))).orElse(0d);
                    }
                }
            }
        }
        return convertFloat(score);
    }

    @Override
    public List<String> getQuestionTypeValue() {
        return Collections.singletonList("matrix_multiple");
    }

    private boolean checkAnswerAllRight(String rowId, JSONObject scoreGidDic, JSONArray answers) {
        // 判断是否为 负值
        // {'3': -1.0, '4': -2.0, '6': -3.0, '7': -4.0}
        List<Boolean> allLtZero = new ArrayList<>();
        List<String> keys = new ArrayList<>(scoreGidDic.keySet());
        for (String key : keys) {
            Double value = scoreGidDic.getDouble(key);
            if (0 != value) {
                allLtZero.add(value < 0);
            }
        }
        if (CollectionUtils.isNotEmpty(allLtZero) && allLtZero.stream()
            .allMatch(Boolean::booleanValue)) {
            return false;
        }
        // 设置的 正确的选项 分数 > 0
        List<String> allScoreGteZeroGids = new ArrayList<>();
        for (String key : keys) {
            Double value = scoreGidDic.getDouble(key);
            if (0 < value) {
                allScoreGteZeroGids.add(key);
            }
        }
        // 答案 提交的选项 gid
        List<String> answersGids = new ArrayList<>();
        for (int i = 0; i < answers.size(); i++) {
            JSONArray it = answers.getJSONArray(i);
            answersGids.add(rowId + "_" + it.getString(0));
        }
        boolean flag = CollectionUtils.isEmpty(allScoreGteZeroGids) || CollectionUtils.isEmpty(answersGids)
            || allScoreGteZeroGids.size() != answersGids.size();
        // 若答案gid 和 配置的全对gid 有差异 则次题答案非全对
        List<Boolean> allRight = answersGids.stream().map(allScoreGteZeroGids::contains).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(allRight) || !allRight.stream().allMatch(Boolean::booleanValue)) {
            flag = true;
        }
        return flag;
    }
}
